/********************************************************************
	created:	2010/07/13
	created:	13:7:2010   14:10
	filename: 	D:\Proj\gcstock\code\C++\Base\GCArray.h
	file path:	D:\Proj\gcstock\code\C++\Base
	file base:	GCArray
	file ext:	h
	author:		Greg Song
	
	purpose:	
*********************************************************************/
#ifndef _GC_ARRAY_H_
#define _GC_ARRAY_H_

#include "GCHeader.h"

namespace gcstock
{
    template<typename T>
        class GCVArray
    {
    public:
        GCVArray():len(0),size(0),array(NULL){};
        ~GCVArray(){if(array&&len){delete[] array;}};
        void add(T& elem);  
        void setSize(int size);
        int  getSize();
        int  getLen();
        
        
        // Operator
        T& operator[](int idx);
    private:
        int len;
        int size;
        T * array;
        
        void release();
        GCVArray<T>* clonePtr();
    };    

    template<typename T>
    T& GCVArray<T>::operator[](int idx)
    {
        if(idx < len)
        {
            return array[idx];
        }
        // raise error, actually exception
    }
    
    
    inline GCVArray<GCCHAR*>::~GCVArray()
    {
        //gccout<<_GCT("Delete array")<<gcendl;
        GCCHAR* p = NULL;
        for(GCINT i = 0;i<len;++i)
        {
            p = array[i];
            delete[] p;
            array[i] = NULL;
        }
        
        if(len&& array)
        {
            delete[] array;
            array = NULL;
            len = 0;
            size = 0;
        }
    }
            
    /////////////////////////////////////////////
    // clonePtr
    // purpose	:
    // input	:
    // output	:
    // return	:
    //
    /////////////////////////////////////////////
    template<typename T>
        GCVArray<T>* GCVArray<T>::clonePtr()
    {
        GCVArray<T>* pTmp = new GCVArray<T>;
        if(!pTmp)
        {
            // throw out exception 
            // out of memory
        }
        pTmp->setSize(len);
        for(int i = 0;i<len;++i)
        {
            T* p = array[i]->clone();
            pTmp->add(p);
        }
        return pTmp;
    }
    
    template<typename T>
        void GCVArray<T>::add(T& elem)
    {
        ++len;
        if (len <= size)
        {       
            array[len - 1] = elem;
        }
        else
        {
            size = len + 20;
            T* tmp = new T[size];
            if(!tmp)
            {
                // throw out exception
                // GSASSERT(tmp);
            }
            if(array && len != 0)
            {
                memcpy(tmp, array, (len - 1) * sizeof(T));
                delete [] array;
            }
            tmp[len - 1] = elem;
                    
            array = tmp;
        }
    }
    
    template<typename T>
        void GCVArray<T>::release()
    {
        if(size > 0)
        {
            delete[] array;
            size    = 0;
            len     = 0;
        }
    }
    
    template<typename T>
        void GCVArray<T>::setSize(int s)
    {
        if(s > 0 && s > size)
        {
            T* tmp = new T[s];
            if(!tmp)
            {
                // throw out exception
                // GSASSERT(tmp);
            }
            if(size > 0)
            {
                memcpy(tmp, array, len);
            }
            array = tmp;
            
            size = s;        
        }
    };
    
    template<typename T>
        int GCVArray<T>::getSize()
    {
        return size;
    };
    
    template<typename T>
        int GCVArray<T>::getLen()
    {
        return len;
    };
}


#endif // _GC_ARRAY_H_